package cn.mibcxb.java.dolphin.common;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.UnknownHostException;

import org.apache.commons.lang3.StringUtils;

import cn.mibcxb.java.dolphin.exception.DataException;
import cn.mibcxb.java.dolphin.exception.DataException.ErrorType;
import cn.mibcxb.java.dolphin.exception.DolphinException;

public class DolphinData implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 3712833627277371091L;

	private InetAddress fromAddr;
	private InetAddress toAddr;

	private Command cmd;
	private String name;
	private String msg;
	private Object raw;

	public DolphinData() {
		super();
	}

	public DolphinData(Command cmd, InetAddress toAddr, String name) {
		super();
		try {
			this.fromAddr = InetAddress.getLocalHost();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		this.toAddr = toAddr;
		this.name = name;
		this.cmd = cmd;
	}

	public Command getCmd() {
		return cmd;
	}

	public void setCmd(Command cmd) {
		this.cmd = cmd;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) throws DolphinException {
		if (StringUtils.isBlank(msg)) {
			throw new DataException(ErrorType.NULL);
		}
		if (msg.getBytes().length > Commons.BUFFER_LENGTH) {
			throw new DataException(ErrorType.OVERFLOW);
		}
		this.msg = msg;
	}

	public Object getRaw() {
		return raw;
	}

	public void setRaw(Object raw) {
		this.raw = raw;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}

	public InetAddress getFromAddr() {
		return fromAddr;
	}

	public void setFromAddr(InetAddress fromAddr) {
		this.fromAddr = fromAddr;
	}

	public InetAddress getToAddr() {
		return toAddr;
	}

	public void setToAddr(InetAddress toAddr) {
		this.toAddr = toAddr;
	}

	/**
	 * This method is used to get the byte array from DolphinData
	 * 
	 * @param data
	 * @return
	 * @throws DolphinException
	 */
	public static byte[] transform2Byte(DolphinData data)
			throws DolphinException {
		if (null != data) {
			ByteArrayOutputStream byteOutStream = null;
			ObjectOutputStream outStream = null;
			try {
				byteOutStream = new ByteArrayOutputStream();
				outStream = new ObjectOutputStream(byteOutStream);
				outStream.writeObject(data);
				outStream.flush();
				byte[] bytes = byteOutStream.toByteArray();
				if (null == bytes) {
					throw new DolphinException("Error in toByteArray");
				} else {
					if (bytes.length > Commons.BUFFER_LENGTH) {
						throw new DolphinException("Message is too long");
					}
					return bytes;
				}
			} catch (IOException e) {
				throw new DolphinException(e);
			} finally {
				if (null != outStream) {
					try {
						outStream.close();
					} catch (IOException e) {
						throw new DolphinException(e);
					}
				}
			}
		}
		return null;
	}

	/**
	 * When receiver get byte array, use this method to rebuild the DolphinData
	 * 
	 * @param bytes
	 * @return
	 * @throws DolphinException
	 */
	public static DolphinData rebuildFromByte(byte[] bytes)
			throws DolphinException {
		if (null != bytes) {
			ByteArrayInputStream byteInStream = null;
			ObjectInputStream inStream = null;
			try {
				byteInStream = new ByteArrayInputStream(bytes);
				inStream = new ObjectInputStream(byteInStream);
				Object object = inStream.readObject();
				if (null == object) {
					throw new DolphinException("Error in readObject");
				} else {
					return (DolphinData) object;
				}
			} catch (IOException e) {
				throw new DolphinException(e);
			} catch (ClassNotFoundException e) {
				throw new DolphinException(e);
			} finally {
				if (null != inStream) {
					try {
						inStream.close();
					} catch (IOException e) {
						throw new DolphinException(e);
					}
				}
			}
		}
		return null;
	}
}
